﻿using System;
using System.Drawing;
using System.Windows.Forms;
using Com.OpenCode.Framework.Core;
using DevExpress.Utils;
using DevExpress.XtraBars;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Columns;
using DevExpress.XtraTreeList.Nodes;

namespace Com.OpenCode.Framework.DevForm
{
    /// <summary>
    ///     树基类。
    /// </summary>
    public class OpenCodeTreeUI : TreeList
    {
        #region 构造函数

        public OpenCodeTreeUI()
        {
            Dock = DockStyle.Fill;
            SelectImageList = _ImageCollection;
            OptionsBehavior.AutoChangeParent = false;
            OptionsBehavior.AutoNodeHeight = false;
            OptionsBehavior.AutoSelectAllInEditor = false;
            OptionsBehavior.CloseEditorOnLostFocus = false;
            OptionsBehavior.Editable = false;
            OptionsBehavior.KeepSelectedOnClick = false;
            OptionsBehavior.ResizeNodes = false;
            OptionsBehavior.SmartMouseHover = false;
            OptionsMenu.EnableColumnMenu = false;
            OptionsMenu.EnableFooterMenu = false;
            OptionsPrint.PrintHorzLines = false;
            OptionsPrint.PrintVertLines = false;
            OptionsSelection.EnableAppearanceFocusedCell = false;
            OptionsView.ShowCheckBoxes = false;
            OptionsView.ShowColumns = false;
            OptionsView.ShowFocusedFrame = false;
            OptionsView.ShowHorzLines = false;
            OptionsView.ShowIndicator = false;
            OptionsView.ShowVertLines = false;
            OptionsView.ShowHorzLines = true;
            OptionsView.ShowVertLines = true;
            OptionsView.ShowColumns = true;
            RowHeight = 23;
            AddColunms();
            AddImages();
            ParentChanged += OpenCodeTree_ParentChanged;
            FocusedNodeChanged += OpenCodeTree_FocusedNodeChanged;
        }

        #endregion

        #region 字段

        private BarManager _BarManager;
        private OpenCodeToolBarMenuUI _ToolBarMenu;
        private OpenCodeRightMenuUI _BlankMenu;
        private bool _ShowBar = true;
        private bool _ShowRightMenu = true;
        private bool _TableStyle = true;
        private ImageCollection _ImageCollection = new ImageCollection();
        private ImageCollection _DefaultCollection=new ImageCollection();

        #endregion

        #region 属性

        /// <summary>
        ///     绑定工具条。
        /// </summary>
        public BarManager BarManager
        {
            get { return _BarManager; }
        }

        /// <summary>
        ///     空白处菜单。
        /// </summary>
        public OpenCodeRightMenuUI BlankMenu
        {
            get { return _BlankMenu; }
            set
            {
                _BlankMenu = value;
                _BlankMenu.Parent = this;
            }
        }

        /// <summary>
        ///     是否显示工具条。
        /// </summary>
        public bool ShowBar
        {
            get { return _ShowBar; }
            set
            {
                _ShowBar = value;
                if (_ToolBarMenu != null)
                {
                    _ToolBarMenu.Visible = _ShowBar;
                }
            }
        }

        public bool TableStyle
        {
            get { return _TableStyle; }
            set
            {
                _TableStyle = value;
                OptionsView.ShowHorzLines = _TableStyle;
                OptionsView.ShowVertLines = _TableStyle;
                OptionsView.ShowColumns = _TableStyle;
            }
        }

        /// <summary>
        ///     是否显示工具条。
        /// </summary>
        public bool ShowRightMenu
        {
            get { return _ShowRightMenu; }
            set { _ShowRightMenu = value; }
        }

        #endregion

        #region 方法

        /// <summary>
        ///     添加列。
        /// </summary>
        public virtual void AddColunms()
        {
            //重写方法添加自定义列。
        }

        public virtual void AddImages()
        {
            if (_ImageCollection.Images.Count==0)
            {
                _DefaultCollection.AddImage(DevFormImage.TreeNode16);
                SelectImageList = _DefaultCollection;
            }
        }

        /// <summary>
        ///     添加右键菜单。
        /// </summary>
        public virtual void AddRightMenu(OpenCodeTreeListNode OpenCodeTreeListNode)
        {
            //重写方法添加自定义菜单。
        }

        /// <summary>
        ///     重写此方法创建右键菜单。
        /// </summary>
        public virtual void CreateRightMenu()
        {
        }

        /// <summary>
        ///     创建列对象。
        /// </summary>
        /// <param name="name">名称。</param>
        /// <param name="visible">可见性。</param>
        /// <param name="width">宽度。</param>
        /// <returns>返回值为创建的列对象。</returns>
        public virtual void CreateColumn(string name, bool visible = true, int width = 100)
        {
            TreeListColumn treeListColumn = new TreeListColumn
            {
                Caption = name,
                MinWidth = width,
                FieldName = name,
                VisibleIndex = Columns.Count
            };
            if (!visible)
            {
                treeListColumn.VisibleIndex = -1;
            }
            treeListColumn.OptionsColumn.AllowEdit = false;
            treeListColumn.OptionsColumn.AllowSize = true;
            treeListColumn.OptionsColumn.AllowSort = true;
            treeListColumn.OptionsColumn.AllowMove = false;
            Columns.AddRange(new[] {treeListColumn});
        }

        public virtual void CreateImage(Image image)
        {
            if (image != null)
            {
                _ImageCollection.AddImage(image);
            }
        }

        public virtual void CreateImage(Addin addin, string image)
        {
            if (addin != null)
            {
                Plugin plugin = addin.Plugin.Search("Icon", "Id", image);
                if (plugin != null)
                {
                    CreateImage((Image) addin.Bulid(plugin));
                }
            }
        }

        /// <summary>
        ///     增加节点。
        /// </summary>
        /// <param name="nodeData"></param>
        /// <param name="parentNode"></param>
        /// <param name="tag"></param>
        /// <returns></returns>
        public override TreeListNode AppendNode(object nodeData, TreeListNode parentNode, object tag)
        {
            TreeListNode treeListNode = base.AppendNode(nodeData, parentNode, tag);
            UpdateRow(treeListNode);
            return treeListNode;
        }

        /// <summary>
        ///     重写添加节点方法。
        /// </summary>
        /// <param name="nodeID"></param>
        /// <param name="owner"></param>
        /// <param name="tag"></param>
        /// <returns></returns>
        protected override TreeListNode CreateNode(int nodeID, TreeListNodes owner, object tag)
        {
            OpenCodeTreeListNode OpenCodeTreeListNode = new OpenCodeTreeListNode(nodeID, owner) {Tag = tag};
            AddRightMenu(OpenCodeTreeListNode);
            if (OpenCodeTreeListNode.RightMenu != null)
            {
                OpenCodeTreeListNode.RightMenu.Parent = this;
            }
            return OpenCodeTreeListNode;
        }

        /// <summary>
        ///     更新行数据。
        /// </summary>
        public virtual void UpdateRow(TreeListNode node)
        {
            AddRightMenu(node as OpenCodeTreeListNode);
            if (_ImageCollection.Images.Count == 0 && node != null)
            {
                node.ImageIndex = 0;
                node.SelectImageIndex = 0;
            }
        }

        /// <summary>
        ///     重写鼠标事件。
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            TreeListHitInfo treeListHitInfo = CalcHitInfo(e.Location);
            FocusedNode = treeListHitInfo.Node;
            //首先获取选中或者没选中节点绑定的右键菜单。
            OpenCodeRightMenuUI rightMenu = BlankMenu;
            if (FocusedNode != null && FocusedNode is OpenCodeTreeListNode)
            {
                OpenCodeTreeListNode OpenCodeTreeListNode = FocusedNode as OpenCodeTreeListNode;
                rightMenu = OpenCodeTreeListNode.RightMenu;
            }
            if (e.Button == MouseButtons.Right)
            {
                if (rightMenu != null)
                {
                    rightMenu.Tag = FocusedNode;
                    if (ShowRightMenu)
                    {
                        rightMenu.Update();
                        rightMenu.ShowPopup(Cursor.Position);
                    }
                }
            }
            else
            {
                base.OnMouseDown(e);
            }
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            if (e.Control && e.KeyCode == Keys.C)
            {
                if (FocusedNode != null && FocusedCellIndex != -1)
                {
                    TreeListColumn treeListColumn = Columns[FocusedCellIndex];
                    string str = FocusedNode.GetDisplayText(treeListColumn.FieldName);
                    if (!string.IsNullOrEmpty(str))
                    {
                        Clipboard.SetText(str);
                    }
                }
            }
        }

        /// <summary>
        ///     父类容器变化事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OpenCodeTree_ParentChanged(object sender, EventArgs e)
        {
            _BarManager = new OpenCodeBarManagerUI {Form = Parent};
            _ToolBarMenu = new OpenCodeToolBarMenuUI(BarManager);
            _ToolBarMenu.Visible = ShowBar;
            CreateRightMenu();
        }

        protected override void OnLoaded()
        {
            base.OnLoaded();
            TreeListNode node = null;
            if (Nodes.Count > 0)
            {
                node = Nodes[0];
            }
            OpenCodeTree_FocusedNodeChanged(this, new FocusedNodeChangedEventArgs(null, node));
        }

        /// <summary>
        ///     选择的节点变化事件。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OpenCodeTree_FocusedNodeChanged(object sender, FocusedNodeChangedEventArgs e)
        {
            OpenCodeRightMenuUI rightMenu = BlankMenu;
            if (e.Node != null && e.Node is OpenCodeTreeListNode)
            {
                rightMenu = (e.Node as OpenCodeTreeListNode).RightMenu;
            }
            if (rightMenu != null)
            {
                //更新菜单状态。
                rightMenu.Tag = FocusedNode;
                if (_ToolBarMenu != null)
                {
                    _ToolBarMenu.ClearLinks();
                    foreach (BarItemLink item in rightMenu.ItemLinks)
                    {
                        if (item is BarButtonItemLink || item is BarCheckItemLink || item is BarEditItemLink)
                        {
                            item.Visible = true;
                            _ToolBarMenu.ItemLinks.Add(item.Item, item.BeginGroup);
                        }
                        else if (item is BarSubItemLink)
                        {
                            BarSubItem addSubItem = new BarSubItem(rightMenu.Manager, item.Caption);
                            BarSubItemLink subItemLink =
                                _ToolBarMenu.ItemLinks.Add(item.Item, item.BeginGroup) as BarSubItemLink;
                            addSubItem.Glyph = item.Item.Glyph;
                            BarSubItem subItem = item.Item as BarSubItem;
                            if (subItem != null && subItem.ItemLinks.Count > 0)
                            {
                                for (int i = 0; i < subItem.ItemLinks.Count; i++)
                                {
                                    BarItemLink itemLink = subItem.ItemLinks[i];
                                    addSubItem.ItemLinks.Add(itemLink.Item, itemLink.BeginGroup);
                                }
                            }
                        }
                    }
                }
            }
        }

        #endregion
    }
}